﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TCPClient
{
    public partial class FormClient : Form
    {
        public FormClient()
        {
            InitializeComponent();
        }
        private delegate void ChangeHisM(string toShowInHisM);//文本框正常变更委托
        private delegate void ReceiveHandle(string strMsg);//文本框接收消息委托
        private delegate void ToMySendFile(byte[] bf);//传输文件委托
        private ChangeHisM changeHisM;//定义委托实例
        private ReceiveHandle receiveHandle;//定义委托实例
        private ToMySendFile toMySendFile;//定义委托实例
        Socket pipeSocket;//传输接口
        Thread bkThreadHandle;//处理接收线程
        private void btnCon_Click(object sender, EventArgs e)//开始按钮事件
        {
            try
            {
                pipeSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPAddress ipTo = IPAddress.Parse(targetIP.Text.Trim());
                pipeSocket.Connect(ipTo, Convert.ToInt32(targetPort.Text.Trim()));
                hisM.AppendText("和目标连接成功"+"\r \n");
                changeHisM = new ChangeHisM(KeepAppendingHisM);
                receiveHandle = new ReceiveHandle(KeepAppendingHisM);
                toMySendFile = new ToMySendFile(MySendFile);
                bkThreadHandle = new Thread(new ThreadStart(Receive));
                bkThreadHandle.IsBackground = true;
                bkThreadHandle.Start();
                localIP.Text = pipeSocket.LocalEndPoint.ToString();
                localIP.ReadOnly = true;
            }
            catch (Exception readyGo)
            {
                MessageBox.Show("连接目标过程出错:" + readyGo.ToString());
            }
        }
        private void Receive()//挂载函数用于挂载委托
        {
            try
            {
                while (true)
                {
                    byte[] tempBuffer = new byte[2048];
                    int received = pipeSocket.Receive(tempBuffer);
                    if (received == 0)
                    {
                        break;
                    }
                    else
                    {
                        if (tempBuffer[0] == 0)
                        {
                            string message = Encoding.Default.GetString(tempBuffer, 1, received - 1);
                            hisM.Invoke(receiveHandle, "目标:" + message);
                        }
                        if (tempBuffer[0] == 1)
                        {
                            AppendHisMMiddle("你接收到大小为:" + (received-1) + "字节的文件");
                            SaveFileDialog sfd = new SaveFileDialog();
                            sfd.InitialDirectory = @"";
                            sfd.Title = "请选择要保存的文件";
                            sfd.Filter = "所有文件|*.*";
                            sfd.ShowDialog(this);
                            string fullPath = sfd.FileName;
                            using (FileStream fs = new FileStream(fullPath, FileMode.OpenOrCreate, FileAccess.Write))
                            {
                                fs.Write(tempBuffer, 1, received - 1);
                            }
                            MessageBox.Show("保存文件成功");
                        }
                    }
                }
            }
            catch (Exception readyGo)
            {
                MessageBox.Show("接收目标发送的消息出错:" + readyGo.ToString());
            }
        }
        private void AppendHisM(string toShowInHisM)//向右添加
        {
            int trueLength = 0;
            int count = 0;
            int chCharCount = 0;
            char[] charArray = toShowInHisM.ToCharArray();
            for (int i = 0; i < charArray.Length; i++)
            {
                char cn = charArray[i];
                byte[] bytes = Encoding.Default.GetBytes(Convert.ToString(cn));
                if (bytes.Length == 1)
                {
                    //英文字符
                    int ascii = bytes[0];
                    trueLength += 1;
                }

                if (bytes.Length == 2)
                {   //双字节字符
                    trueLength += 2;
                    count++;
                    int hightByte = 256 + bytes[0];
                    int lowByte = 256 + bytes[1];
                    int ascii = (256 * hightByte + lowByte) - 256 * 256;
                    if (ascii >= -20319 && ascii < -10247)
                    {   //中文字符
                        chCharCount++;
                    }
                }
            }
            for (int i = 0; i <89-trueLength; i++)
            {
                hisM.AppendText(" ");
            }
            hisM.AppendText(toShowInHisM + "\r \n");
        }
        private void AppendHisMMiddle(string toShowInHisM)//在中间添加
        {
            int trueLength = 0;
            int count = 0;
            int chCharCount = 0;
            char[] charArray = toShowInHisM.ToCharArray();
            for (int i = 0; i < charArray.Length; i++)
            {
                char cn = charArray[i];
                byte[] bytes = Encoding.Default.GetBytes(Convert.ToString(cn));
                if (bytes.Length == 1)
                {
                    //英文字符
                    int ascii = bytes[0];
                    trueLength += 1;
                }

                if (bytes.Length == 2)
                {   //双字节字符
                    trueLength += 2;
                    count++;
                    int hightByte = 256 + bytes[0];
                    int lowByte = 256 + bytes[1];
                    int ascii = (256 * hightByte + lowByte) - 256 * 256;
                    if (ascii >= -20319 && ascii < -10247)
                    {   //中文字符
                        chCharCount++;
                    }
                }
            }
            for (int i = 0; i < 89/2 - trueLength/2; i++)
            {
                hisM.AppendText(" ");
            }
            hisM.AppendText(toShowInHisM + "\r \n");
        }
        private void KeepAppendingHisM(string toAppendToHisM)//正常显示在左
        {
            hisM.AppendText(toAppendToHisM + " \r \n");
        }

        private void btnSM_Click(object sender, EventArgs e)//点击发送消息按钮
        {
            try
            {
                string toShowInHisM = localIP.Text+":"+MtoSend.Text.Trim();
                byte[] tempBuffer = Encoding.Default.GetBytes(toShowInHisM);
                List<byte> tempList = new List<byte>();
                tempList.Add(0);
                if (isSpread.Checked)
                {
                    tempList.Add(1);
                }
                else
                {
                    tempList.Add(0);
                }
                tempList.AddRange(tempBuffer);
                byte[] newBuffer = tempList.ToArray();
                pipeSocket.Send(newBuffer);
                AppendHisM("你:"+ MtoSend.Text.Trim());
                MtoSend.Clear();
            }
            catch (Exception readyGo)
            {
                MessageBox.Show("发送消息出错:" + readyGo.Message);
            }
        }

        private void btnDis_Click(object sender, EventArgs e)
        {
            pipeSocket.Close();
            bkThreadHandle.Abort();
        }

        private void btnSF_Click(object sender, EventArgs e)//选择文件按钮
        {
            Thread t = new Thread((ThreadStart)(() =>
            {
                OpenFileDialog ofd = new OpenFileDialog();
                ofd.Title = "请选择文件";
                ofd.Filter = "所有文件(*.*)|*.*";
                ofd.InitialDirectory = @"";
                if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    fPath.Text = ofd.FileName;
                }
            }
            ));
            t.SetApartmentState(ApartmentState.STA);
            t.Start();
            t.Join();
        }
        private void MySendFile(byte[] sendBuffer)//发送文件挂载事件
        {
            try
            {
                pipeSocket.Send(sendBuffer, SocketFlags.None);
                MessageBox.Show("已经成功发送指定文件");
            }
            catch (Exception readyGo)
            {
                MessageBox.Show("发送文件出错:" + readyGo.Message);
            }
        }
        private void SF_Click(object sender, EventArgs e)//点击发送文件按钮
        {
            List<byte> tempList = new List<byte>();
            string fullPath = fPath.Text.Trim();
            using (FileStream fs = new FileStream(fullPath, FileMode.Open, FileAccess.Read))
            {
                byte[] tempBuffer = new byte[fs.Length];
                int received = fs.Read(tempBuffer, 0, tempBuffer.Length);
                tempList.Add(1);
                if (isSpread.Checked)
                {
                    tempList.Add(1);
                }
                else
                {
                    tempList.Add(0);
                }
                tempList.AddRange(tempBuffer);
                byte[] newBuffer = tempList.ToArray();
                AppendHisMMiddle("您将发送的文件,它的大小是:" + fs.Length.ToString()+"字节");
                SF.Invoke(toMySendFile, newBuffer);
            }
        }

        private void FormClient_Load(object sender, EventArgs e)//用于设置跨线程访问
        {
            Control.CheckForIllegalCrossThreadCalls = false;
        }
    }
}
